#!/usr/bin/env python
#Copyright (c) 2011 Isaac Dawson (WBTS Project)
#Permission is hereby granted, free of charge, to any person obtaining a copy 
#of this software and associated documentation files (the "Software"), to deal 
#in the Software without restriction, including without limitation the rights 
#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
#copies of the Software, and to permit persons to whom the Software is furnished
#to do so, subject to the following conditions:
#
#The above copyright notice and this permission notice shall be included in all
#copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
#THE SOFTWARE.
import sys
import os
sys.path.append(os.curdir)

from wbts.config.wbts_config import *

def get_yesno(msg):
    while( 1 ):
        x = raw_input(msg)
        if (x == 'y' or x == 'Y'):
            return True
        elif (x == 'n' or x == 'N'):
            return False
        else:
            print "Answer not understood, please type y or n."


def prompt_value(prompt, value, config, section, name, type=None):
    while (1):
        print "[Default: %s]"%value
        x = raw_input(prompt)
        if (x != ''):
            value = x
        ret = config.addCfgValue(section, name, value, type)
        if (ret == True):
            print '----'
            print "Selected %s"%value
            print '----'
            return value
            
def get_dns_values(config, path):
    section = 'DNSSettings'
    named_root = path+'named_root'+os.sep
    
    prompt_value('Insert path to store our dns records: ',
                 named_root, config, section, "named_root", "path")
    
    enable_alt_server = get_yesno('Would you like to enable an alternate DNS server? (y/n): ')
    if (enable_alt_server):
        alt_server = '8.8.8.8'
        prompt_value('Insert alternate DNS server to handle non-authortative records: ',
                     alt_server, config, section, "alt_server", "host")
        alt_port = 53
        prompt_value('Insert the port for the alternate DNS server: ',
                     alt_port, config, section, "alt_port", "port")      
    return

def get_mgmt_values(config, path):
    section = 'ManagementSettings'
    mgmt_root = path+'web_root'+os.sep+'mgmt'+os.sep  
    mgmt_port = 9999
    prompt_value('Insert the path to the management web files: ',
                 mgmt_root, config, section, "mgmt_root", "path")
    prompt_value('Insert the port to bind our management service to: ',
                 mgmt_port, config, section, "mgmt_port", "port")
        
        
def get_web_values(config, path):
    section = 'WebSettings'
    shared_root = path+'web_root'+os.sep+'shared'+os.sep
    http_port = 80
    
    prompt_value('Insert the directory for the shared web files: ',
                 shared_root, config, section, "shared_root", "path")
    prompt_value('Insert the port to bind our vhost server to: ',
                 http_port, config, section, "http_port", "port")
    

def get_ssl_values(config, path):
    section = 'SSLSettings'
    enable_ssl = get_yesno('Would you like to enable SSL/HTTPS (y/n): ')
    if (enable_ssl):
        print '----'
        print 'SSL will be enabled.'
        print '----'
    
        ssl_cert = path+'server.pem'
        ssl_port = 443
        prompt_value("Insert the path to the server's SSL certificate: ",
                 ssl_cert, config, section, "ssl_cert", "file")
        prompt_value('Insert the port to bind our vhost server to: ',
                 ssl_port, config, section, "ssl_port", "port")
    else:
        config.addCfgValue(section, 'enabled', 'false')
        



def get_vhostmap_values(config, path):
    section = "VirtualHostMappings"
    print "You must add attacker.com and victim.com for javascript test cases"
    print "to work.",
    attacker_default = "vhost1"
    victim_default = "vhost2"
    vhost_root = path+'web_root'+os.sep+'vhost_root'+os.sep
    
    print "Please note the vhost directory will be appended to: \n%s"%vhost_root
    host_msg = 'Please choose the vhost directory for the %s host: '
    attack_hosts = ["attacker.com", "www.attacker.com",
                    "default", "attacker.victim.com"]
    victim_hosts = ["victim.com", "www.victim.com", "sub.victim.com"]

    for host in attack_hosts:
        prompt_value(host_msg%host, vhost_root+"vhost1",
                     config, section, host, "path")

    for host in victim_hosts:
        prompt_value(host_msg%host, vhost_root+"vhost2",
                     config, section, host, "path")

    get_more = get_yesno("Would you like to add more hosts? (y/n): ")
    if (get_more):
        while(1):

            host = raw_input("Enter the hostname (x to quit): ")
            if (host == 'x' or host == 'X'):
                break
            if (host == ""):
                print "Sorry no hostname entered, please try again."
                continue

            vhost_dir = raw_input("Enter the vhost directory (x to quit): ")
            if (vhost_dir == 'x' or vhost_dir == 'X'):
                break
            if (vhost_dir == ""):
                print "Sorry no vhost directory entered, please try again"
                continue

            config.addCfgValue(section, host, vhost_dir, "path")
            
    return

def get_vhostproc_values(config, path):
    section = "VirtualHostProcessors"
    defaults = {'.cgi': 'twcgi.CGIScript', '.asis': 'static.ASISProcessor',
                '.rpy': 'script.ResourceScript'}
    
    for ext,proc in defaults.items():
        addit = get_yesno('Would you like to add the %s processor? (y/n): '%ext)
        if (addit):
            config.addCfgValue(section, ext, proc, "processor")
    
    get_more = get_yesno("Would you like to add more processors? (y/n): ")
    if (get_more):
        while(1):
            ext = raw_input('Enter the extension to add (x to quit): ')
            if (ext == 'x' or ext == 'X'):
                break
            if (ext == ""):
                print "Sorry no extension entered, please try again."
                continue
            if (not ext.startswith('.')):
                print "Sorry extension must start with a ."
                continue
            print "If you need to add an interpeter (such as /bin/php) seperate"
            print "the python processor class and the interpreter by a ,"
            print "Example: processors.PHPProcessor,/bin/php"
            processor = raw_input('Enter the processor (x to quit): ')
            if (processor == 'x' or processor == 'X'):
                break
            if (processor == ""):
                print "Sorry no processor entered, please try again"
                continue
            config.addCfgValue(section, ext, processor, "processor")
            
    return

def get_db_values(config, path):
    section = 'DBClientSettings'
    db_name = 'wbts'
    db_class = 'pydictdb.WBTSPydictDB'
    pyconnstr = path+'data'+os.sep+'wbts.dat'
    mongoconnstr = "127.0.0.1:27017:wbts"
    dbpath = path+'wbts'+os.sep+'storage'+os.sep
    
    db_name = prompt_value('Insert the name of our data store/database: ',
                           db_name, config, section, "db_name", "db_name")
    
    db_class = prompt_value('Insert the name of our db class (module must exist in %s!): '%
                            dbpath, db_class, config, section,
                            "db_class", "class")
    
    if (db_class == 'pydictdb.WBTSPydictDB'):
        print "pydictdb.WBTSPydictDB takes a filepath for the connect string."
        prompt_value('Please provide the connection string: ',
                     pyconnstr, config, section, "db_connectstring",
                     "db_connectstring")

    elif (db_class == 'mongodb.WBTSMongoDB'):
        print "mongodb.WBTSMongoDB takes a host:port:dbname (ex: 127.0.0.1:27017:%s)"%db_name
        prompt_value('Please provide the connection string: ',
                     mongoconnstr, config, section, "db_connectstring",
                     "db_connectstring")
    else:
        prompt_value('Please provide the connection string:',
                     "Unknown", config, section, "db_connectstring",
                     "db_connectstring")

def get_priv_values(config, path):
    section = 'PrivilegeSettings'
    userid = 1
    groupid = 1
    prompt_value('Insert the (system) user id to shed privileges to: ',
                 userid, config, section, "userid", "id")
    prompt_value('Insert the (system) group id to shed privileges to: ',
                 groupid, config, section, "groupid", "id")
    return

if __name__ == '__main__':
    print "Welcome to the WBTS Configuration Generator."
    print "This file will create our default wbts.cfg file. Please note, this"
    print "script will NOT create the directories and they should exist prior"
    print "to running WBTS."
    print
    print '-'*80
    
    wbts_config = WBTSConfig()
    try:
        wbts_config.openCfg()
    except IOError, msg:
        print "Unable to open wbts.cfg for writing: %s"
        exit(1)
    current_path = os.getcwd() + os.sep
    print '===='
    print "Configuring Management Settings"
    print '===='
    get_mgmt_values(wbts_config, current_path)
    print '===='
    print "Configuring Web Server Settings"
    print '===='
    get_web_values(wbts_config, current_path)
    print '===='
    print "Configuring DNS Settings"
    print '===='
    get_dns_values(wbts_config, current_path)
    print '===='
    print "Configuring SSL Settings"
    print '===='
    get_ssl_values(wbts_config, current_path)
    print '===='
    print "Configuring Virtual Hosts"
    print '===='
    get_vhostmap_values(wbts_config, current_path)
    print '===='
    print "Configuring Virtual Host Processors"
    print '===='
    get_vhostproc_values(wbts_config, current_path)
    print '===='
    print "Configuring Database Settings"
    print '===='
    get_db_values(wbts_config, current_path)
    
    if (os.name == 'posix'):
        print '===='
        print "Configuring Privilege Settings"
        print '===='
        get_priv_values(wbts_config, current_path)
        
    print "Saving Configuration File"
    wbts_config.saveCfg()
    print "Configuration complete, you may now start wbts by running: "
    if (os.name == 'nt'):
        print "twistd.py -noy wbts.tac"
    else:
        print "twistd -noy wbts.tac"
    
    